package org.example.movie;


import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.Mat;
import org.example.RtspInfo;

import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.Laplacian;
import static org.bytedeco.opencv.global.opencv_imgproc.cvtColor;
import static org.bytedeco.opencv.global.opencv_imgproc.COLOR_BGR2GRAY;
import static org.bytedeco.opencv.global.opencv_core.*;

/**
 * 图形模糊度
 * @author zehua
 * @date 2023/11/7 16:01
 * @Description TODO 考虑校验摄像头是否 有遮挡物
 * 1.获取视频帧：从RTSP流中捕获每一帧图像。
 * 2.转换为灰度图：因为清晰度评估通常与颜色无关，所以首先将图像转换为灰度图像。
 * 3.应用拉普拉斯算子：对灰度图像应用拉普拉斯算子，这可以通过OpenCV中的Laplacian函数实现。
 * 4.计算方差：计算拉普拉斯图像的方差。图像越清晰，边缘和细节越多，计算出的方差值就越大。
 * <p>
 * 阈值判断：设定一个阈值，当计算出的方差值低于这个阈值时，认为图像是模糊的。
 * @since V1.1.0
 */
public class BlurDetection {

    public static void main(String[] args) throws Exception {
        assessQuality(RtspInfo.RTSP_URL_CAMERA);
    }


    public static void assessQuality(String rtspUrl) throws FrameGrabber.Exception {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspUrl);
        OpenCVFrameConverter.ToMat converterToMat = new OpenCVFrameConverter.ToMat();
        Mat stddev = new Mat();
        try {
            grabber.start();
            Frame frame;
            int i = 0;
            while ((frame = grabber.grabImage()) != null) {
                i++;
                Mat mat = converterToMat.convert(frame);
                // 间隔30帧
                if (mat != null && i % 30 == 0) {
                    //  图像变为灰色图像
                    Mat gray = new Mat();
                    cvtColor(mat, gray, COLOR_BGR2GRAY);
                    // 应用拉普拉斯算子
                    Mat laplacianImage = new Mat();
                    Laplacian(gray, laplacianImage, CV_8U);
                    // 计算方差 标准差越大说明图像质量越好
                    meanStdDev(laplacianImage, new Mat(), stddev);
                    double aDouble = stddev.createIndexer().getDouble();
                    String fileName = "frame" + i + "_src.jpg";
                    if (aDouble < 20){
                        String laplacianImageName = "frame" + i + "_laplacianImage.jpg";
                        // 记录模糊的图像
                        imwrite(fileName, mat);
                        imwrite(laplacianImageName, laplacianImage);
                    }
                    System.out.println(fileName+"-----------------"+aDouble);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                converterToMat.close();
                grabber.close();
            } catch (FFmpegFrameGrabber.Exception e) {
                e.printStackTrace();
            }
        }
    }
}
